package environment;
import java.awt.Dimension;
import java.awt.Graphics2D;
//import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import point.ObjectPoint;
import force.CenterMass;
//import force.Force;
import force.Gravity;
import force.Viscosity;
import force.WallRepulsion;
import line.Line;


/**
 * Simulates objects moving around in a bounded environment.
 * 
 * @author Robert C. Duvall
 */
public class Simulation {
    /**
     * @param myMasses list stores the masses
     */
    private ArrayList<ObjectPoint> myMasses;
    /**
     * @param myWallreplusionforce
     */
    private List<WallRepulsion> myWallreplusionforce;
    /**
     * @param mySprings list stores the springs
     */
    private ArrayList<Line> mySprings;
    /**
     * @param myContainer the canvas class
     */
    private Canvas myContainer;

    /**
     * Create a Canvas with the given size.
     * @param container Canvas class
     */
    public Simulation(Canvas container) {
        myMasses = new ArrayList<ObjectPoint>();
        mySprings = new ArrayList<Line>();
        myWallreplusionforce = new ArrayList<WallRepulsion>();
        myContainer = container;
    }
/**
 * 
 * @param mass mass point
 */
    public final void add(ObjectPoint mass) {
        myMasses.add(mass);
    }

    /**
     * 
     * @return the mass center of the system
     */
    public final double getxCenter() {
        double xCenter = 0;
        for (ObjectPoint m : myMasses) {
            xCenter += m.getCenter().getX();
        }
        return xCenter / myMasses.size();
    }
    /**
     * 
     * @return the mass center of the system
     */
    public final double getyCenter() {
        double yCenter = 0;
        for (ObjectPoint m : myMasses) {
            yCenter += m.getCenter().getY();
        }
        return yCenter / myMasses.size();
    }

    /**
     * 
     * @param g apply gravity force to mass
     */
    public final void add(Gravity g) {
        for (ObjectPoint m : myMasses) {
            m.setGravity(g);
        }
    }
/**
 * 
 * @param c apply center force to mass
 */
    public final void add(CenterMass c) {
        for (ObjectPoint m : myMasses) {
            m.setCentermass(c);

        }
    }
    /**
     * 
     * @param v apply viscosity force to mass
     */
    public final void add(final Viscosity v) {
        for (ObjectPoint m : myMasses) {
            m.setViscosity(v);

        }
    }
    /**
     * 
     * @param w apply wall repulsion force to mass
     */
    public final void add(final WallRepulsion w) {
        myWallreplusionforce.add(w);
    }

/**
 * apply repulsion force
 */
    public final void applywallrepulsionforce() {
        for (WallRepulsion w:myWallreplusionforce) {
        for (ObjectPoint m : myMasses) {
            m.setWallrepulsion(w);

        }
        }
    }
    /**
     * 
     * @param spring Line object
     */
    public final void add(final Line spring) {
        mySprings.add(spring);
    }


    /**
     * Paint all shapes on the canvas.
     * 
     * @param pen used to paint shape on the screen
     */
    public final void paint(final Graphics2D pen) {
        for (Line s : mySprings) {
            s.paint(pen);
        }
        for (ObjectPoint m : myMasses) {
            m.paint(pen);
        }
    }

    /**
     * Called by each step of timer, multiple times per second.
     *
     * This should update the state of the animated shapes by just
     * a little so they appear to move over time.
     * @param dt time
     */
    public final void update(final double dt) {
        updateMovers(dt);
    }
/**
 * 
 * @param dt time
 */
    final void updateMovers(final double dt) {
        for (Line s : mySprings) {
            s.update(this, dt);
        }
        for (ObjectPoint m : myMasses) {
            m.update(this, dt);
        }
    }

    /**
     * @return Returns size (in pixels) of the game area.
     */
    public final Dimension getSize() {
        return myContainer.getSize();
    }

    /**
     * 
     * @return line array list
     */
    public final ArrayList<Line> getLine() {
        return mySprings;
    }
    /**
     * 
     * @return object point array list
     */
    public final ArrayList<ObjectPoint> getObjectPoint() {
        return myMasses;
    }
/**
 * 
 * @param id the number of the object
 * @return get the mass object
 */
    public final ObjectPoint getMass(final int id) {
        for (ObjectPoint m : myMasses) {
            if (m.match(id)) {
                return m;
            }
        }
        return null;
    }
}
